package com.xyy.saas.payment.adpater.unionpay;

import com.alibaba.fastjson.JSON;
import com.unionpay.acp.sdk.SDKConfig;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.PayBo;
import com.xyy.saas.payment.cores.enums.PayModeEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.vo.UnionPayConfigVo;
import com.xyy.saas.payment.payment.core.dto.PayDto;
import com.xyy.saas.payment.payment.core.dto.RefundDto;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.UnionPayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

/**
 * @author niuhaiyu
 * @ClassName UnionPayOnlineGwHanlder
 * @Description 描述
 * @Date 2021/6/29 下午3:01
 */
@Component
public class UnionPayOnlineGwHanlder extends AbstractUnionPayChannelHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(UnionPayOnlineGwHanlder.class);

    @Override
    public String getMethod() {
        return PayModeEnum.ONLINE_GW.getMode();
    }

    @Override
    public PayBo pay(PayDto payDto) throws PaymentException {
        PayBo payBo = null;
        try {
            LOGGER.info("UnionPayOnlineGwHanlder pay begin payDto:{}", JSON.toJSONString(payDto));
            PayBo appPayBo = redisClient.get(payDto.getPayMode() + payDto.getPayNo() + payDto.getChannel(), PayBo.class);
            if (appPayBo != null) {
                LOGGER.info("UnionPayOnlineGwHanlder pay end get from redis appPayBo:{}", JSON.toJSONString(appPayBo));
                return appPayBo;
            }

            UnionPayConfigVo unionPayConfigVo = channelSettingManager.getUnionPayConfig(payDto.getBusinessOrderType(), payDto.getPayMode());

            if (unionPayConfigVo == null) {
                throw new PaymentException(ResultCodeEnum.UNIONPAY_CONFIG_NOT_EXITS);
            }

            unionPayUtils.init(unionPayConfigVo);
            SortedMap params = joinPayRequestData(payDto);
            //生成签名
            Map<String, String> signMap = unionPayUtils.signData(params);
            String sbHtml = unionPayUtils.createHtml(SDKConfig.getConfig().getFrontRequestUrl(), signMap);
            payBo = new PayBo();
            payBo.setPayLoad(sbHtml);
            payBo.setPayNO(payDto.getPayNo());
            LOGGER.info("UnionPayOnlineGwHanlder pay result:{}", JSON.toJSONString(payBo));
            return payBo;

        }catch (PaymentException e) {
            LOGGER.error("UnionPayOnlineGwHanlder pay error payDto:{}", JSON.toJSON(payDto), e);
            payBo = null;
            throw e;
        }catch (Exception e) {
            LOGGER.error("UnionPayOnlineGwHanlder pay error payDto:{}", JSON.toJSON(payDto), e);
            payBo = null;
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if(payBo != null){
                //默认超时时间,如果业务有传超时时间就按照他们的时间+5400秒
                Integer expire = 5400;
                if (null != payDto.getTimeExpire() && payDto.getTimeExpire().after(new Date())) {
                    expire = DateUtil.getSecondsFromToday(payDto.getTimeExpire()).intValue() + expire;
                }
                redisClient.set(payDto.getPayMode() + payDto.getPayNo() + payDto.getChannel(), payBo, expire);
            }

        }

    }



    @Override
    public SortedMap joinRefundRequestData(RefundDto refundDto){
        SortedMap paramsMap = unionPayUtils.joinRefundRequestData(refundDto);
        //渠道类型，这个字段区分B2C网关支付和手机wap支付；07：PC,平板  08：手机
        paramsMap.put("channelType", "07");
        //商户退款单号
        paramsMap.put("orderId", refundDto.getRefundNo());
        //原交易查询流水号
        paramsMap.put("origQryId", refundDto.getChannelChargeId());
        //订单发送时间
        paramsMap.put("txnTime", DateUtil.currentTimestamp2String(DateUtil.YYYYMMDDHHMMSS));
        //交易金额，消费撤销时需和原消费一致
        paramsMap.put("txnAmt", String.valueOf(refundDto.getAmount()));
        //请求方保留域
        paramsMap.put("reqReserved", "07");
        return paramsMap;
    }


    @Override
    public SortedMap joinPayRequestData(PayDto payDto) {
        SortedMap params = unionPayUtils.joinPayRequestData(payDto);

        //渠道类型，这个字段区分B2C网关支付和手机wap支付；07：PC,平板  08：手机
        params.put("channelType", "07");
        String backPayNotifyUrl = ApolloUtil.getProperty(UnionPayUtils.UNIONPAY_BACK_PAY_NOTIFY_URL);
        String frontNotiryUrl = ApolloUtil.getProperty(UnionPayUtils.UNIONPAY_FRONT_PAY_NOTIFY_URL);

        //后台通知地址
        params.put("backUrl", backPayNotifyUrl);
        //前台通知地址
        params.put("frontUrl", frontNotiryUrl);
        params.put("reqReserved", "07");

        return params;
    }
}
